package com.xingkeduo.dao.database.mysql.config;

import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;
import com.xingkeduo.dao.database.DatabaseAccessObject;
import com.xingkeduo.dao.database.DatabaseProxy;
import com.xingkeduo.dao.database.mysql.condition.MysqlOperationCondition;
import com.xingkeduo.util.pojo.base.BaseQuery;
import com.xingkeduo.util.pojo.base.BaseTable;

/**
 * 文件概述
 *
 * @author wangxilong <wangxilong@xingkeduo.com>
 * @version id:v0.1 18-12-28 下午11:24
 * @package BeautyOS
 * @copyright Copyright (c) XKD 2019
 */
@Configuration
@Conditional(MysqlOperationCondition.class)
public class MysqlOperationConfig <T extends BaseTable<T>, Q extends BaseQuery<Q>>{
    @Value("${db.mysql.operation.driver}")
    private String driver;
    @Value("${db.mysql.operation.url}")
    private String url;
    @Value("${db.mysql.operation.user}")
    private String user;
    @Value("${db.mysql.operation.password}")
    private String password;
    @Value("${db.mysql.operation.maxActive}")
    private int maxActive;
    @Value("${db.mysql.operation.initialSize}")
    private int initialSize;
    @Value("${db.mysql.operation.maxWait}")
    private long maxWait;
    @Value("${db.mysql.operation.minIdle}")
    private int minIdle;

    @Bean(name = "mysqlOperationDataSource")
    public DataSource initDataSource() throws SQLException {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        dataSource.setFilters("stat");// 监控数据库
        dataSource.setMaxActive(maxActive);// 连接池最大使用连接数量
        dataSource.setInitialSize(initialSize);// 初始化连接大小
        dataSource.setMaxWait(maxWait);// 获取连接最大等待时间，单位是毫秒
        dataSource.setMinIdle(minIdle);// 连接池最小空闲连接数量
        dataSource.setTimeBetweenEvictionRunsMillis(60000);// 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
        dataSource.setMinEvictableIdleTimeMillis(300000);// 配置一个连接在池中最小生存的时间，单位是毫秒
        dataSource.setRemoveAbandoned(true);// 打开removeAbandoned功能
        dataSource.setRemoveAbandonedTimeout(1800);// removeAbandoned超时时间，单位是秒
        dataSource.setLogAbandoned(true);// 关闭abanded连接时输出错误日志
        dataSource.setValidationQuery("SELECT 'x'");
        dataSource.setTestWhileIdle(true);
        dataSource.setTestOnBorrow(false);
        dataSource.setTestOnReturn(false);
        dataSource.setPoolPreparedStatements(true);
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(50);

        return dataSource;
    }

    @Bean(name = "mysqlOperationTransactionManager")
    public DataSourceTransactionManager initTransactionManager() {
        try {
            return new DataSourceTransactionManager(initDataSource());
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Bean(name = "mysqlOperationSqlSessionFactory")
    public SqlSessionFactory initSqlSessionFactory(@Qualifier("mysqlOperationDataSource") DataSource dataSource)
            throws Exception {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setTypeAliasesPackage("com.xingkeduo.pojo.table,com.xingkeduo.pojo.query");
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
        sqlSessionFactoryBean.setConfigLocation(resolver.getResource("classpath:mybatis.xml"));
        sqlSessionFactoryBean.setVfs(SpringBootVFS.class);

		return sqlSessionFactoryBean.getObject();
    }

    @Bean(name = "mysqlOperationSqlSessionTemplateFromMybatis")
    public SqlSessionTemplate initSqlSessionTemplate(
            @Qualifier("mysqlOperationSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = "mysqlOperationDao")
    public DatabaseAccessObject<T, Q> initMysqlOperationDao(
            @Qualifier("mysqlOperationSqlSessionTemplateFromMybatis") SqlSessionTemplate sqlSessionTemplate) {
        return new DatabaseProxy<T, Q>().build(sqlSessionTemplate);
    }
}
